﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Web.Mvc;
using Flagwind.Runtime.Serialization;

namespace Flagwind.Web
{
	public abstract class ControllerBase : System.Web.Mvc.Controller
	{
		#region 私有字段

		private TextSerializationSettings _serializationSettings;

		#endregion

		#region 保护属性

		protected TextSerializationSettings SerializationSettings
		{
			get
			{
				return _serializationSettings;
			}
			set
			{
				if(value == null)
					throw new ArgumentNullException();

				_serializationSettings = value;
			}
		}

		#endregion

		#region 序列化方法

		[NonAction]
		protected new JsonResult Json(object data)
		{
			return Json(data, null , null, JsonRequestBehavior.AllowGet, this._serializationSettings);
		}

		[NonAction]
		protected new JsonResult Json(object data, string contentType)
		{
			return Json(data, contentType, null, JsonRequestBehavior.AllowGet, this._serializationSettings);
		}

		[NonAction]
		protected new JsonResult Json(object data, string contentType, Encoding contentEncoding)
		{
			return Json(data, contentType, contentEncoding, JsonRequestBehavior.AllowGet, this._serializationSettings);
		}

		[NonAction]
		protected new JsonResult Json(object data, JsonRequestBehavior behavior)
		{
			return Json(data, null, null, behavior, this._serializationSettings);
		}

		[NonAction]
		protected new JsonResult Json(object data, string contentType, JsonRequestBehavior behavior)
		{
			return Json(data, contentType, null, behavior, this._serializationSettings);
		}

		[NonAction]
		protected new JsonResult Json(object data, string contentType, Encoding contentEncoding, JsonRequestBehavior behavior)
		{
			return Json(data, contentType, contentEncoding, behavior, this._serializationSettings);
		}

		[NonAction]
		protected virtual JsonResult Json(object data, string contentType, Encoding contentEncoding, JsonRequestBehavior behavior, TextSerializationSettings serializationSettings)
		{
			var result = new JsonResult(data);
			result.ContentType = contentType;
			result.ContentEncoding = contentEncoding;
			result.JsonRequestBehavior = behavior;
			result.SerializerSettings = serializationSettings ?? this._serializationSettings;

			return result;
		}

		#endregion

		#region 接口响应方法

		/// <summary>
		/// 创建一个成功 API 响应结果。
		/// </summary>
		/// <param name="content">要写入到响应的内容。</param>
		/// <param name="message">要写入到响应的消息。</param>
		/// <returns><see cref="ApiResult"/> 结果对象。</returns>
		[NonAction]
		protected ApiResult Success(object content = null, string message = null)
		{
			return this.Api(ApiStatusCode.Success, message, content);
		}

		/// <summary>
		/// 创建一个失败 API 响应结果。
		/// </summary>
		/// <param name="message">失败错误消息。</param>
		/// <returns><see cref="ApiResult"/> 结果对象。</returns>
		[NonAction]
		protected ApiResult Failure(string message = null)
		{
			return this.Api(ApiStatusCode.Failure, message);
		}

		/// <summary>
		/// 创建一个验证错误 API 响应结果。
		/// </summary>
		/// <param name="member">获取产生验证错误的成员。</param>
		/// <param name="message">获取产生验证错误的消息。</param>
		/// <returns><see cref="ApiResult"/> 结果对象。</returns>
		[NonAction]
		protected ApiResult ValidationError(string member, string message)
		{
			return this.ValidationError(new List<ValidationError>{ new ValidationError(member, message) });
		}

		/// <summary>
		/// 创建一个验证错误 API 响应结果。
		/// </summary>
		/// <param name="errors">验证错误项集合。</param>
		/// <returns><see cref="ApiResult"/> 结果对象。</returns>
		[NonAction]
		protected ApiResult ValidationError(IEnumerable<ValidationError> errors)
		{
			return this.Api(ApiStatusCode.InvalidParam, null, errors);
		}

		/// <summary>
		/// 使用状态码、消息字符串、响应内容和序列化配置创建一个 <see cref="ApiResult"/> 结果对象。
		/// </summary>
		/// <param name="code">返回给客户端的状态码。</param>
		/// <param name="message">与状态码对应的消息字符串。</param>
		/// <param name="content">要写入到响应的内容。 </param>
		/// <param name="serializationSettings">序列化配置实例。</param>
		/// <returns><see cref="ApiResult"/> 结果对象。</returns>
		[NonAction]
		protected virtual ApiResult Api(ApiStatusCode code, string message = null, object content = null, TextSerializationSettings serializationSettings = null)
		{
			var result = new ApiResult(code, content, message);

			result.SerializerSettings = serializationSettings ?? this._serializationSettings;

			return result;
		}

		#endregion
	}
}